package com.eclipse.e20200201_多线程同步.同步锁_代码块锁;

public class SyncTest implements Runnable {
    //共享资源变量
    static int count = 0;
    private byte[] mBytes = new byte[0];

    @Override
    public synchronized void run() {
        increaseCount();
    }

    private void increaseCount() {
        //假设省略了其他操作的代码。
        //……………………
        synchronized (SyncTest.class) {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + ":" + count++);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        Thread thread1 = new Thread(syncTest1, "thread1");
        Thread thread2 = new Thread(syncTest2, "thread2");
        thread1.start();
        thread2.start();
    }
    /**
    synchronized修饰代码块

  首先这个使用时的场景是：在某些情况下，我们编写的方法体可能比较大，同时存在一些比较耗时的操作，而需要同步的代码又只有一小部分，如果直接对整个方法进行同步操作，可能会得不偿失，此时我们可以使用同步代码块的方式对需要同步的代码进行包裹，这样就无需对整个方法进行同步操作了。所以他的作用范围为synchronizd（obj）{}的这个大括号中
【demo4】
从输出结果看出，这个demo并没有保证线程安全，因为我们指定锁为this，指的就是调用这个方法的实例对象。这里我们new了两个不同的实例对象syncTest1，syncTest2，所以有两个锁，thread1与thread2分别进入自己传入的对象锁的线程执行increaseCount方法，做成线程不安全。如果把demo4的成员变量注释放开，并将mBytes传入synchronized后面的括号中，也是线程不安全的结果。这里之所以加上mBytes这个对象是为了说明synchronized后面的括号中是可以指定任意对象充当锁的，而零长度的byte数组对象创建起来将比任何对象都经济。当然，如果要使用这个经济实惠的锁并保证线程安全，那就不能new出多个不同实例对象出来啦。如果你非要想new两个不同对象出来，又想保证线程同步的话，那么synchronized后面的括号中可以填入SyncTest.class，表示这个类对象作为锁，自然就能保证线程同步啦。使用方法为：

总结

修饰普通方法 一个对象中的加锁方法只允许一个线程访问。但要注意这种情况下锁的是访问该方法的实例对象， 如果多个线程不同对象访问该方法，则无法保证同步。

修饰静态方法 由于静态方法是类方法， 所以这种情况下锁的是包含这个方法的类，也就是类对象；这样如果多个线程不同对象访问该静态方法，也是可以保证同步的。

修饰代码块 其中普通代码块 如Synchronized（obj） 这里的obj 可以为类中的一个属性、也可以是当前的对象，它的同步效果和修饰普通方法一样；Synchronized方法 （obj.class）静态代码块它的同步效果和修饰静态方法类似。

   
     */
}